//=============================================================================
/**
 *
 *	@file	pkthln_result.c
 *	@brief	ポケスロン競技結果発表
 *	@author	Nozomu Saito -> Genya Hosaka(引継ぎ)
 *
 */
//=============================================================================
#include "common.h"
#include "pkthln_result.h"
#include "../../pkthln_obj_common.h"

#include "system/wipe.h"
#include "system/arc_util.h"
#include "system/render_oam.h"
#include "system/msgdata_util.h"
#include "system/snd_tool.h"
#include "system/snd_play.h"
#include "msgdata/msg.naix"
#include "msgdata/msg_pokethlon.h"
#include "system/pmfprint.h"
#include "system/brightness.h"

#include "../../pkthln_comm_pack.h"

#include "../pkthln_clact.h"
#include "../pkthln_act_def.h"
#include "../score_board.h"
#include "../evt_logo.h"
#include "../evt_msg.h"
#include "../evt_cats.h"

#include "../pkthev_rslt.naix"
#include "../pkthev_oped.naix"
#include "../event_se_def.h"

#include "result_tag.h"

typedef struct RSLT_COMM_CHILD_WORK_tag * RSLT_COMM_CHILD_PTR;

//=============================================================================
/**
 *								定数定義
 */
//=============================================================================
#define RESULT_HEAP_SIZE	( 0x40000 )

#define END_MES_RAND_MAX (5)	// 終了メッセージに使うランダムのMAX

#define RESULT_PAL_NUM	(9)		//フォント+順位+ポケアイコン3+フレーム4
#define RESULT_OBJ_NUM	(30)	//(順位+アイコン+名前+成績+得点+フレーム)x5
#define TOTAL_PAL_NUM	( RESULT_PAL_NUM )
#define TOTAL_OBJ_NUM	( RESULT_OBJ_NUM )
#define BOARD_ACT_NUM	((1+2+3)*4)	//（ボード1+名前2+点数3）ｘ4
#define ACT_MAX	(BOARD_ACT_NUM)

#define ACT_RES_NUM	(3)		//「〜しゅもくめ」ロゴ・競技ロゴ・ボード

#define	SUB_DISP_OFS	(300)			//サブ画面開始オフセット

//フォントOAM必要キャラ数
#define F_OAM_NAME_CHR_SIZE		(8*2)
#define F_OAM_RECORD_CHR_SIZE	(10*2)
#define F_OAM_SCORE_CHR_SIZE	(5*2)
#define F_OAM_TOTAL_CHR_SIZE	( F_OAM_NAME_CHR_SIZE+F_OAM_RECORD_CHR_SIZE+F_OAM_SCORE_CHR_SIZE )

//タグ動作関連
#define DISP_TAG_NUM	(4)
#define NEW_TAG_X	(256)
#define SLIDE_TAG_Y (5*8)
#define SLIDE_SPEED	( 80 )
#define MV_START_WAIT ( 10 )
#define TAG_DISP_WAIT (10)
#define DOWN_SPEED	(8)

#define RND_DISP_TIMING	(4)　///< 点滅間隔

#define	COL_N_BLACK	( GF_PRINTCOLOR_MAKE( 1, 2, 0 ) )		// フォントカラー：白

// -- BG
enum
{
	BG_FRM_M_BASE = GF_BGL_FRAME0_M,
	BG_FRM_M_TEXT = GF_BGL_FRAME1_M,
	BG_FRM_S_BASE = GF_BGL_FRAME0_S,
	BG_FRM_S_TEXT = GF_BGL_FRAME1_S,
	BG_FRM_S_EVTMSG = GF_BGL_FRAME2_S,
	BG_FRM_S_EVT  = GF_BGL_FRAME3_S,
	BG_USE_NUM = 6,
	RSLT_FONT_PAL = 15,
};

// -- 使用するBGテーブル
static const u8 c_BG_UseList[ BG_USE_NUM ] = {
	GF_BGL_FRAME0_M, GF_BGL_FRAME1_M,
	GF_BGL_FRAME0_S, GF_BGL_FRAME1_S, GF_BGL_FRAME2_S, GF_BGL_FRAME3_S,
};

static const u8 c_BG_ModeList[ BG_USE_NUM ] = {
	GF_BGL_MODE_TEXT, GF_BGL_MODE_TEXT,
	GF_BGL_MODE_TEXT, GF_BGL_MODE_TEXT, GF_BGL_MODE_256X16, GF_BGL_MODE_256X16
};

// -- OBJ
enum{
	RES_IDX_OFS = 1000,
	OBJ_TRAINER_NUM = 4,
	OBJ_MMO_MAX = OBJ_TRAINER_NUM + 1, // トレーナー＋司会者

	CAP_ID_S_TALKER = 0,
	CAP_ID_S_MMO_MAX,
	CAP_ID_MAX,

	OBJ_ID_MAX = ACT_MAX + CAP_ID_MAX, // @@@ 暫定
};

enum {
	CHR_ID_S_MMO = RES_IDX_OFS,
	CHR_ID_MAX,
};

enum {
	PAL_ID_S_MMO = RES_IDX_OFS,
	PAL_ID_MAX,
};

enum {
	CEL_ID_MMO = RES_IDX_OFS,
	CEL_ID_MAX,
};

enum {
	ANM_ID_MMO = RES_IDX_OFS,
	ANM_ID_MAX,
};

//--------------------------------------------------------------
///	タグ シーケンス
//==============================================================
typedef enum{
	TAG_SEQ_SLIDE_IN,	//新規スライドイン
	TAG_SEQ_SLIDE_IN_ALL, //初回4つタグのスライドイン
	TAG_SEQ_MOVE_DOWN,	//表示中タグの下方向移動
	TAG_SEQ_DISP_WAIT,	//表示待ち
}TAG_SEQ;

//--------------------------------------------------------------
///	チェックする方向
//==============================================================
typedef enum {
	CHECK_DIR_LEFT,		//画面左側到達
	CHECK_DIR_DOWN,		//画面下到達
}CHECK_DIR;



//=============================================================================
/**
 *								構造体定義
 */
//=============================================================================

//--------------------------------------------------------------
///	子機→親機への通信データ
//==============================================================
typedef struct RSLT_COMM_CHILD_WORK_tag{
	u8 MsgSeq;		///< メッセージシーケンサ
	u8 bPrinting;
	u8 EndFlag;
	u8 Padding[33];
} RSLT_COMM_CHILD_WORK;

//--------------------------------------------------------------
///	通信用ワーク
//==============================================================
typedef struct
{
	u8 EndMesRand;		//1 byte	終了メッセージの乱数
	u8 MsgSeq;
	u8 EndFlag;
	u8 bMsgWait;
	// -- 未使用 --
	u8 dummy[32];
}RSLT_PARENT_DATA;		//36 byte

//--------------------------------------------------------------
///	タグデータ
//==============================================================
typedef struct TAG_DATA_tag
{
	BOOL Valid;
	RTAG_PTR TagPtr;
	int MvWait;
	BOOL bSndPlayed; ///< スライドインサウンドが終了したらTRUE
}TAG_DATA;

//--------------------------------------------------------------
///	タグコントローラ
//==============================================================
typedef struct TAG_CNT_tag
{
	RTAG_CNT_PTR RTagCntPtr;
	TAG_DATA	DispTag[DISP_TAG_NUM];
	TAG_DATA	SlideTag;
	int Wait;
	u8 Seq;
	u8 TotalTagNum;
	u8 NowTagNum;
	u8 EntryPoint;	//0〜3
	u8 RsltReadPoint;	//0〜TotaltagNum-1 (最大11)
	BOOL bFirstNo1; //最初の一位が到達したらTRUEになるフラグ
}TAG_CNT;

//--------------------------------------------------------------
///	メインワーク
//==============================================================
typedef struct PE_RESULT_tag
{
	int HeapID;
	int Counter;
	int RndDispCount;
	GF_BGL_INI *bgl;
	PKTHLN_CLACT_CNT_PTR ActCntPtr;
	SC_BOARD_PTR BoardPtr;
	MSG_CNT_PTR	MsgCnt;
	TAG_CNT		TagControler;
	EVT_LOGO_PTR logo;
	GF_BGL_BMPWIN Win;

	CATS_SYS_PTR csp;
	CATS_RES_PTR crp;
	CATS_ACT_PTR cap[ CAP_ID_MAX ];

	int	MsgSeq;	///< メッセージ同期用シーケンサ
	BOOL EndFlag;
}PE_RESULT;


//=============================================================================
/**
 *							プロトタイプ宣言
 */
//=============================================================================
static BOOL RESULT_Func_Phase(PKTHLN_PTR work, u8 *seq);
static void SetVramBank(void);
static void InitBG(GF_BGL_INI * ini, HEAPID HeapID);
static void SetBG(PE_RESULT_PTR ptr );

//タグ関連
static void InitTagControler(TAG_CNT *tagCntPtr, const int inHeapID,
		GF_BGL_INI *bgl, PKTHLN_PTR pkthln_ptr);
static void SetupTagControler(TAG_CNT *tagCntPtr, PKTHLN_PTR work,
		const u8 inTotalRec, const BOOL inIconFlg);
static void MoveTag(TAG_DATA* data, const int inX, const int inY);
static void MoveDispTag(TAG_CNT *tagCntPtr, const int inX, const int inY);
static BOOL CheckMoveArrive(TAG_DATA *data, const CHECK_DIR inFlg);
static void SetDispWaitSeq(TAG_CNT *tagCntPtr, const int inWait);
static BOOL TagSeqMain(TAG_CNT *tagCntPtr, PKTHLN_PTR work);
static void EntryTagToDispList(TAG_CNT *tagCntPtr, RTAG_PTR tag_ptr, const int inMvWait);
static void EntryTagToSlide(TAG_CNT *tagCntPtr, RTAG_PTR tag_ptr, const int inMvWait);
static void ClearTagEntry( TAG_DATA *outTagData );
static BOOL IsNoneDispTag( TAG_CNT *tagCntPtr );
static RTAG_PTR MakeTag( TAG_CNT *tagCntPtr, PKTHLN_PTR work, const int inX, const int inY );
static void ClearTag(TAG_CNT *tagCntPtr, TAG_DATA *outTagData);
static TAG_DATA* GetLastTag(TAG_CNT *tagCntPtr);
static u32 GetStartMsg( PKTHLN_PTR work );
static u32 GetEndMsg( PKTHLN_PTR work );
static void CATS_Create( PE_RESULT_PTR ptr );
static void CATS_Delete( PE_RESULT_PTR ptr );
static void CATS_LoadRes( PE_RESULT_PTR ptr );
static void CATS_AddMapModel( PE_RESULT_PTR ptr );
static BOOL RSLT_CommMain( PKTHLN_PTR work );

PKTHLN_FUNC ResultFuncTbl[] = {
	RESULT_Func_Phase,
};


static void CreateBmpWin( GF_BGL_BMPWIN* Win, GF_BGL_INI* bgl, HEAPID HeapID )
{
	//ＢＮＰウィンドウデータ
	static const BMPWIN_DAT BmpData = {
			BG_FRM_M_TEXT, 8, 1, 16, 2, RSLT_FONT_PAL, 1,
	};

	GF_ASSERT( bgl );

	GF_BGL_BmpWinAddEx( bgl, Win, &BmpData );
	GF_BGL_CharFill( bgl, BG_FRM_M_TEXT, 0, 1, 0 );

	// メインBGにパレットを展開
	SystemFontPaletteLoad(PALTYPE_MAIN_BG, RSLT_FONT_PAL*0x20, HeapID );
	// BG2の拡張パレット領域にフォント用パレットを展開
	SystemFontPaletteLoad( PALTYPE_SUB_BG_EX, 0x4000, HeapID );
}

static void PrintStaticMessage( GF_BGL_BMPWIN* Win, HEAPID HeapID )
{
	WORDSET* word;
	MSGDATA_MANAGER* msgman;
	STRBUF* strbuf;

	GF_BGL_BmpWinDataFill( Win, 0 );

	msgman = MSGMAN_Create( MSGMAN_TYPE_DIRECT, ARC_MSG, NARC_msg_pokethlon_dat, HeapID );
	word = WORDSET_Create( HeapID );

	strbuf = MSGDAT_UTIL_AllocExpandString( word, msgman, msg_pkthln_rs_cap, HeapID );

	GF_STR_PrintColor( Win, FONT_SYSTEM, strbuf, 0, 0, MSG_NO_PUT, COL_N_BLACK, NULL );

	STRBUF_Delete( strbuf );
	WORDSET_Delete( word );
	MSGMAN_Delete( msgman );

	GF_BGL_BmpWinOn( Win );
}

//=============================================================================
/**
 *								外部公開関数
 */
//=============================================================================

//--------------------------------------------------------------------------------------------
/**
 * 初期化関数
 *
 * @param	work		ポケスロンワークポインタ
 * @param	*pParam		パラメータ
 *
 * @return	TRUE
 */
//--------------------------------------------------------------------------------------------
PTH_RC PE_RESULT_InitFunc(PKTHLN_PTR work, void *pParam)
{
	PE_RESULT_PTR ptr = PTFrame_GetEventWorkPtr(work);
	u8 seq = PTFrame_GetSubSeq(work);
	switch(seq){
	case 0:
		{
			int heap_id;
			sys_CreateHeap( HEAPID_POKETHLON, HEAPID_PT_RESULT, RESULT_HEAP_SIZE );

			heap_id = HEAPID_PT_RESULT;

			sys_VBlankFuncChange( NULL, NULL );	// VBlankセット
			sys_HBlankIntrSet( NULL,NULL );		// HBlankセット

			GF_Disp_GX_VisibleControlInit();
			GF_Disp_GXS_VisibleControlInit();
			GX_SetVisiblePlane( 0 );
			GXS_SetVisiblePlane( 0 );

			//VRAMバンク割り当て
			SetVramBank();
			//アプリケーションメモリー
			ptr = PTFrame_AllocEventWork(work, sizeof(PE_RESULT));
			MI_CpuClear8( ptr, sizeof(PE_RESULT));

			ptr->HeapID = heap_id;

			// タッチフォントをロード
			FontProc_LoadFont( FONT_TOUCH, ptr->HeapID );
			//BGLアロケーション
			ptr->bgl = GF_BGL_BglIniAlloc(heap_id);
			//メッセージコントローラ
			ptr->MsgCnt = MSG_CNT_Create( ptr->HeapID );
			//タグコントローラ
			InitTagControler(&ptr->TagControler, heap_id, ptr->bgl, work);
			//競技ロゴ
			ptr->logo = EvtLogo_Init( PTFrame_GetEventCode(work), ptr->HeapID );

			CATS_Create( ptr );

		}

		//下画面をメインにする
		sys.disp3DSW = DISP_3D_TO_SUB;
		GF_Disp_DispSelect();

		//次のシーケンスへ
		PTFrame_IncSubSeq(work);
		break;
	case 1:
		{
			PKTHLN_ACT_SETUP_PRM param = {
				ACT_MAX,ACT_RES_NUM,{ACT_RES_NUM,ACT_RES_NUM,ACT_RES_NUM,ACT_RES_NUM}
			};

			//アクター関連
			ptr->ActCntPtr = PkthlnClAct_Init(ptr->HeapID, &param);

			//上下画面幅設定
			PkthlnClAct_SetDispDistance(ptr->ActCntPtr,
										0, 0,
										0, (SUB_DISP_OFS*FX32_ONE) );		//上下画面をまたがないので、少し間を空ける

			//タグコントローラセットアップ
			{
				RSLT_PTR rslt = PTFrame_GetResultPtr(work);
				int num = RSLT_GetDataNum(rslt);
				BOOL icon = RSLT_IsValidPokeIcon(rslt);
				SetupTagControler(&ptr->TagControler, work, num, icon);
			}
			//スコアボード
			ptr->BoardPtr = ScoreBoard_Init(ptr->HeapID, ptr->bgl, ptr->ActCntPtr);
			ScoreBoard_SetAct(ptr->BoardPtr, 2);

			PkthlnClAct_Trans(ptr->ActCntPtr);

			//ボードアクター
			ScoreBoard_Put(ptr->BoardPtr, work, SUB_DISP_OFS);

			//CATSアクター
			CATS_LoadRes( ptr );
			CATS_AddMapModel( ptr );
			CATS_MapModelDraw( ptr->cap[ CAP_ID_S_TALKER ], CATS_GetMapModelTexIdx( 2 ), TEX_ASEQ_NPC_FRONT, ptr->HeapID );
		}

		//次のシーケンスへ
		PTFrame_IncSubSeq(work);
		break;
	case 2:
		PTFrame_SetDefaultVBlankFunc(ptr->bgl);	// VBlankセット
		//BG初期化
		InitBG(ptr->bgl, ptr->HeapID);
		//BGセット
		EvtLogo_Setup( ptr->logo, ptr->bgl );
		SetBG(ptr);
		EvtLogo_SetBG( ptr->logo );
		GF_Disp_GXS_VisibleControl( GX_PLANEMASK_BG2, VISIBLE_OFF );
		GF_Disp_GXS_VisibleControl( GX_PLANEMASK_BG3, VISIBLE_OFF );
		//メッセージコントローラ 初期化
		MSG_CNT_Init( ptr->MsgCnt, ptr->bgl, BG_FRM_S_TEXT, PTFrame_GetGameType( work ), PTFrame_GetSaveData( work ) );
		EvtLogo_Print( ptr->logo );
		// アフィンスクロール
		{
			enum{ DIFF_X = 0, DIFF_Y = 16 };
			MtxFx22 mtx;
			fx32 scale;

			scale = FX32_ONE;
			mtx._00 = scale;
			mtx._01 = 0;
			mtx._10 = 0;
			mtx._11 = scale;

			SVC_WaitVBlankIntr();          // Waiting the end of VBlank interrup
			GF_BGL_AffineScrollSet( ptr->bgl, BG_FRM_S_EVT, GF_BGL_SCROLL_X_INC,	DIFF_X, &mtx, 128, 96 );
			GF_BGL_AffineScrollSet( ptr->bgl, BG_FRM_S_EVT, GF_BGL_SCROLL_Y_DEC,	DIFF_Y, &mtx, 128, 96 );
			GF_BGL_AffineScrollSet( ptr->bgl, BG_FRM_S_EVTMSG, GF_BGL_SCROLL_X_INC, DIFF_X, &mtx, 128, 96 );
			GF_BGL_AffineScrollSet( ptr->bgl, BG_FRM_S_EVTMSG, GF_BGL_SCROLL_Y_DEC, DIFF_Y, &mtx, 128, 96 );
		}
		// BMPWIN 初期化
		CreateBmpWin( &ptr->Win, ptr->bgl, ptr->HeapID );
		PrintStaticMessage( &ptr->Win, ptr->HeapID );
		//次のシーケンスへ
		PTFrame_IncSubSeq(work);
		break;
	case 3:
		//親のとき、初回送信データを作成
		if ( PTFrameGetCurrentID(work) == COMM_PARENT_ID )
		{
			COMM_EVENT_COMMON_DATA* data;
			data = PTFrame_GetEvtComCmnData(work);
			{
				RSLT_PARENT_DATA* parent = PKTHLN_CommPack_GetData( &data->SendShareData );
				parent->EndMesRand = gf_mtRand() % END_MES_RAND_MAX;
				HOSAKA_PRINT("set rand :%d \n", parent->EndMesRand);
			}
		}

		if( PTFrame_GetGameType(work) == PKTHLN_GAME_COMM )
		{
			// 通信アイコンを起動
			WirelessIconEasyPokethlon( NNS_G2D_VRAM_TYPE_2DMAIN );
			WirelessIconEasy_ObjModeXLU();
			WirelessIconOAM_Trans();
		}

		//ＯＢＪの表示
		GF_Disp_GX_VisibleControl( GX_PLANEMASK_OBJ, VISIBLE_ON );		// SUB DISP OBJ ON
		GF_Disp_GXS_VisibleControl( GX_PLANEMASK_OBJ, VISIBLE_ON );		// SUB DISP OBJ ON

		//BGの表示
		GF_Disp_GXS_VisibleControl( GX_PLANEMASK_BG2, VISIBLE_ON );
		GF_Disp_GXS_VisibleControl( GX_PLANEMASK_BG3, VISIBLE_ON );

		//描画を許可
		PTFrame_SetDraw(work, TRUE);

		//次のシーケンスへ
		PTFrame_IncSubSeq(work);
		break;
	case 4:
		//リザルトＢＧＭ
		Snd_BgmPlay(SEQ_GS_PT_RESULT);
		//フェードイン
		WIPE_SYS_Start(	WIPE_PATTERN_WMS, WIPE_TYPE_FADEIN,
					WIPE_TYPE_FADEIN, WIPE_FADE_BLACK,
					WIPE_DEF_DIV, WIPE_DEF_SYNC, ptr->HeapID );

		//次のシーケンスへ
		PTFrame_IncSubSeq(work);
		break;
	case 5:
		if( WIPE_SYS_EndCheck() )
		{
			//初期化終了
			return PTH_RC_END;
		}
		break;

	default : GF_ASSERT(0);
	}
	return PTH_RC_LOOP;
}

//----------------------------------------------------------------------------
/**
 *	@brief	初期化関数
 *
 *	@param	work		ポケスロンワークポインタ
 *	@param	*pParam		パラメータ
 *
 *	@return TRUE
 */
//-----------------------------------------------------------------------------
BOOL PE_RESULT_DrawFunc(PKTHLN_PTR work, void *pParam)
{
	PE_RESULT_PTR ptr = PTFrame_GetEventWorkPtr(work);
	PkthlnClAct_Draw(ptr->ActCntPtr);
	CATS_Draw( ptr->crp );
	//タグ描画
	RTAG_Draw(ptr->TagControler.RTagCntPtr);
	return TRUE;
}

//--------------------------------------------------------------------------------------------
/**
 * 終了関数
 *
 * @param	work		ポケスロンワークポインタ
 * @param	*pParam		パラメータ
 *
 * @return	TRUE
 */
//--------------------------------------------------------------------------------------------
BOOL PE_RESULT_EndFunc(PKTHLN_PTR work, void *pParam)
{
	int i;
	PE_RESULT_PTR ptr = PTFrame_GetEventWorkPtr(work);

	sys_VBlankFuncChange( NULL, NULL );	// VBlankセット
	sys_HBlankIntrSet( NULL,NULL );		// HBlankセット

	FontProc_UnloadFont( FONT_TOUCH );

	// 輝度リセット
	G2_SetBlendBrightness( PLANEMASK_ALL , 0);

	EvtLogo_End( ptr->logo );

	GF_BGL_BmpWinDel( &ptr->Win );

	MSG_CNT_Delete( ptr->MsgCnt );

	//BG削除
	for( i=0; i<BG_USE_NUM; i++ )
	{
		GF_BGL_BGControlExit(ptr->bgl, c_BG_UseList[i] );
	}

	//スコアボード解放
	ScoreBoard_End(ptr->BoardPtr);
	//タグコントローラ削除
	RTAG_End(ptr->TagControler.RTagCntPtr);
	//アクター解放
	PkthlnClAct_Free(ptr->ActCntPtr);
	CATS_Delete( ptr );
	//BGL解放
	sys_FreeMemoryEz(ptr->bgl);		//<<フォントOAMでBMP使ってるから、その解放のあとに呼ぶ

	//イベントワーク解放
	PTFrame_FreeEventWork(work);

	// 上下画面を元に戻しておく
	sys.disp3DSW = DISP_3D_TO_MAIN;
	GF_Disp_DispSelect();

	//ヒープ解放
	sys_DeleteHeap( HEAPID_PT_RESULT );

	// 通信アイコン撤去
	WirelessIconEasyEnd();

	return TRUE;
}


//=============================================================================
/**
 *								static関数
 */
//=============================================================================

//--------------------------------------------------------------------------------------------
/**
 * VRAM設定		ポケスロンでは、ポケモン表示だけで0x30000必要となる。
 * VRAM_AB(0x40000)でないとはいらん
 *
 * @param	none
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
static void SetVramBank(void)
{
	GF_BGL_DISPVRAM tbl = {
		GX_VRAM_BG_128_A,				// メイン2DエンジンのBG
		GX_VRAM_BGEXTPLTT_NONE,			// メイン2DエンジンのBG拡張パレットM
		GX_VRAM_SUB_BG_128_C,			// サブ2DエンジンのBG
		GX_VRAM_SUB_BGEXTPLTT_32_H,		// サブ2DエンジンのBG拡張パレット

		GX_VRAM_OBJ_128_B,				// メイン2DエンジンのOBJ
		GX_VRAM_OBJEXTPLTT_NONE,		// メイン2DエンジンのOBJ拡張パレット

		GX_VRAM_SUB_OBJ_16_I,			// サブ2DエンジンのOBJ
		GX_VRAM_SUB_OBJEXTPLTT_NONE,	// サブ2DエンジンのOBJ拡張パレット

		GX_VRAM_TEX_NONE,				// テクスチャイメージスロット
		GX_VRAM_TEXPLTT_NONE			// テクスチャパレットスロット
	};
	GF_Disp_SetBank( &tbl );
}

//--------------------------------------------------------------------------------------------
/**
 * @brief	BG初期化
 * @param	*ini		BGL
 * @return	none
 */
//--------------------------------------------------------------------------------------------
static void InitBG(GF_BGL_INI * ini, HEAPID HeapID)
{
	{	/* BG SYSTEM */
		GF_BGL_SYS_HEADER BGsys_data = {
			GX_DISPMODE_GRAPHICS, GX_BGMODE_0, GX_BGMODE_5, GX_BG0_AS_2D,
		};
		GF_BGL_InitBG( &BGsys_data );
	}

	{
		int i;
		GF_BGL_BGCNT_HEADER bg_data[ BG_USE_NUM ] = {
			// -- MAIN --
			{	// BG_0 ベース
				0,0,0x800,0,GF_BGL_SCRSIZ_256x256,GX_BG_COLORMODE_16,
				GX_BG_SCRBASE_0x0000,GX_BG_CHARBASE_0x04000,GX_BG_EXTPLTT_01,
				1,0,0,FALSE
			},
			{	// BG_1 テキスト
				0,0,0x800,0,GF_BGL_SCRSIZ_256x256,GX_BG_COLORMODE_16,
				GX_BG_SCRBASE_0x0800,GX_BG_CHARBASE_0x08000,GX_BG_EXTPLTT_01,
				0,0,0,FALSE
			},
			// -- SUB --
			{	// BG_0 ベース
				0,0,0x800,0,GF_BGL_SCRSIZ_256x256,GX_BG_COLORMODE_16,
				GX_BG_SCRBASE_0x0000,GX_BG_CHARBASE_0x04000,GX_BG_EXTPLTT_01,
				3,0,0,FALSE
			},
			{	// BG_1 テキスト
				0,0,0x800,0,GF_BGL_SCRSIZ_256x256,GX_BG_COLORMODE_16,
				GX_BG_SCRBASE_0x0800,GX_BG_CHARBASE_0x08000,GX_BG_EXTPLTT_01,
				0,0,0,FALSE
			},
			{	// BG_2 イベント名用アフィンテキスト
				0,0,0x800,0,GF_BGL_SCRSIZ_256x256,GX_BG_COLORMODE_256,
				GX_BG_SCRBASE_0x1000,GX_BG_CHARBASE_0x10000,GX_BG_EXTPLTT_01,
				1,0,0,FALSE
			},
			{	// BG_3 イベント名(アフィン
				0,0,0x800,0,GF_BGL_SCRSIZ_256x256,GX_BG_COLORMODE_256,
				GX_BG_SCRBASE_0x1800,GX_BG_CHARBASE_0x14000,GX_BG_EXTPLTT_01,
				2,0,0,FALSE
			},
		};

		for( i=0; i<BG_USE_NUM; i++ )
		{
			GF_BGL_BGControlSet( ini, c_BG_UseList[i], &(bg_data[i]), c_BG_ModeList[i] );
			GF_BGL_ScrClear( ini, c_BG_UseList[i] );
			GF_BGL_ClearCharSet( c_BG_UseList[i], 64, 0, HeapID );
		}
	}

}

//--------------------------------------------------------------------------------------------
/**
 * @brief	BGキャラセット
 * @param	per		リザルト管理ポインタ
 * @return	none
 */
//--------------------------------------------------------------------------------------------
static void SetBG(PE_RESULT_PTR ptr)
{
	enum{ TEXT_BASE_CHR_OFS = 0x20*0x20*0x20 };

	//キャラ
	ArcUtil_BgCharSet(ARC_PKTHEV_RESULT, NARC_pkthev_rslt_result_bg_s_NCGR,
						ptr->bgl, BG_FRM_S_BASE, 0, 0, FALSE, ptr->HeapID);
	//スクリーン
	ArcUtil_ScrnSet(ARC_PKTHEV_RESULT, NARC_pkthev_rslt_result_bg_s02_NSCR,
						ptr->bgl, BG_FRM_S_BASE, 0, 0, FALSE, ptr->HeapID);

	//キャラ
	ArcUtil_BgCharSet(ARC_PKTHEV_RESULT, NARC_pkthev_rslt_result_bg_s_NCGR,
						ptr->bgl, BG_FRM_S_TEXT, 0, 0, FALSE, ptr->HeapID);
	//スクリーン
	ArcUtil_ScrnSet(ARC_PKTHEV_RESULT, NARC_pkthev_rslt_result_bg_s_NSCR,
						ptr->bgl, BG_FRM_S_TEXT, 0, 0, FALSE, ptr->HeapID);

	//パレット
	ArcUtil_PalSet( ARC_PKTHEV_RESULT, NARC_pkthev_rslt_result_bg_NCLR,
						PALTYPE_SUB_BG, 0, 0, ptr->HeapID );

	//下画面

	//キャラ
	ArcUtil_BgCharSet(ARC_PKTHEV_RESULT, NARC_pkthev_rslt_result_bg_NCGR,
						ptr->bgl, BG_FRM_M_BASE, 0, 0, FALSE, ptr->HeapID);
	//スクリーン
	ArcUtil_ScrnSet(ARC_PKTHEV_RESULT, NARC_pkthev_rslt_result_bg_NSCR,
						ptr->bgl, BG_FRM_M_BASE, 0, 0, FALSE, ptr->HeapID);
	//パレット
	ArcUtil_PalSet( ARC_PKTHEV_RESULT, NARC_pkthev_rslt_result_bg_NCLR,
						PALTYPE_MAIN_BG, 0, 0, ptr->HeapID );
}

//-----------------------------------------------------------------------------
/**
 *	@brief	通信時：親機のEndFlagを待つ
 *
 *	@param	PKTHLN_PTR work
 *
 *	@retval	TRUE:終了
 */
//-----------------------------------------------------------------------------
static BOOL COMM_CheckEndFlag( PKTHLN_PTR work )
{
	COMM_EVENT_COMMON_DATA* data = PTFrame_GetEvtComCmnData(work);
	RSLT_PARENT_DATA* parent = PKTHLN_CommPack_GetData( &data->ReciveShareData );

	return ( parent->EndFlag );
}

//----------------------------------------------------------------------------
/**
 *	@brief	メイン関数
 *
 *	@param	work		ポケスロンポインタ
 *	@param	*seq		シーケンサ
 *
 *	@return	BOOL		TRUE：終了	FALSE：継続
 */
//-----------------------------------------------------------------------------
static BOOL RESULT_Func_Phase(PKTHLN_PTR work, u8 *seq)
{
	int i;
	BOOL rc;
	PE_RESULT_PTR ptr;
	BOOL bCommWait = FALSE;

	ptr = PTFrame_GetEventWorkPtr(work);
	rc = FALSE;

	// BGM再開処理
	Snd_MePlayCheckBgmPlay();

	// 通信同期処理
	if( PTFrame_GetGameType(work) == PKTHLN_GAME_COMM )
	{
		bCommWait = RSLT_CommMain( work );
	}

	//メッセージ駆動
	MSG_CNT_Main( ptr->MsgCnt );

	if( MSG_CNT_IsPrinting( ptr->MsgCnt ) == FALSE && bCommWait == FALSE )
	{
		WORDSET* WordSet = MSG_CNT_GetWordSet( ptr->MsgCnt );
		int code = MSG_ID_NONE;

		switch(*seq){
		case 0:
			code = GetStartMsg( work );
			(*seq)++;
			break;
		case 1:
			//タグメイン
			if ( TagSeqMain(&ptr->TagControler, work) )
			{
				int i;
				RESULT_DATA* result[4];

				for( i=0; i<4; i++ )
				{
					result[i] = RSLT_GetResultDataPtr( PTFrame_GetResultPtr(work), i );
				}

				// 一位が複数いたらメッセージ切替
				if( result[0]->Rank == result[1]->Rank )
				{
					code = msg_pkthln_rs_se02_01_02;
				}
				else
				{
					WORDSET_RegisterPlayerName( WordSet, 0, PTFrame_GetMyStatus( work, result[0]->NetID ) );
					code = msg_pkthln_rs_se02_01_01;
				}

				(*seq)++;
			}
			break;
		case 2:
			// MAIN LCD 黒く
			ChangeBrightnessRequest( 16, -8, 0, PLANEMASK_ALL, MASK_MAIN_DISPLAY );
			// 第二対象面を設定
			SetBrightNessPlaneMask( PLANEMASK_ALL, PLANEMASK_ALL );
			// BlendAlpha係数を設定
			G2_ChangeBlendAlpha( 16, 0 );
			(*seq)++;
			break;
		case 3:
			if( IsFinishedBrightnessChg( MASK_MAIN_DISPLAY ) )
			{
				// この　きょうぎせいせき　から
				code = msg_pkthln_rs_se02_02;
				(*seq)++;
			}
			break;
		case 4:
			//実得点セット
			for(i=0;i<ENTRY_MEMBER_NUM_MAX;i++)
			{
				int score;
				PKTHLN_EVT_CODE evt_code = PTFrame_GetEventCode(work);
				score = RSLT_GetEvtScore(PTFrame_GetResultPtr(work), evt_code, i);
				if( score > 999 ){ score = 999; } // 念のため上限を超えていたらフォロー
				ScoreBoard_SetScore(ptr->BoardPtr,  score, i);
			}

			// SUB LCD 画面ホワイトフラッシュ
			ChangeBrightnessRequest( 16, BRIGHTNESS_NORMAL, BRIGHTNESS_WHITE, PLANEMASK_ALL, MASK_SUB_DISPLAY );

			(*seq)++;
			break;
		case 5:
			// ワイプ、輝度変更中は処理スキップ
			if( IsFinishedBrightnessChg( MASK_SUB_DISPLAY ) )
			{
				(*seq)++;
			}
			break;
		case 6:
			// 終了メッセージ
			code = GetEndMsg( work );
			// 子機の終了フラグを立てる
			ptr->EndFlag = TRUE;
			HOSAKA_PRINT("end code :%d \n", code);
			(*seq)++;
			break;
		case 7:
			{
				// 通信時は親機のEndFlagを待つ
				if( PTFrame_GetGameType(work) == PKTHLN_GAME_ALONE || COMM_CheckEndFlag( work ) )
				{
					//ホワイトアウト
					WIPE_SYS_Start(	WIPE_PATTERN_WMS, WIPE_TYPE_FADEOUT,
								WIPE_TYPE_FADEOUT, WIPE_FADE_WHITE,
								WIPE_DEF_DIV*2, WIPE_DEF_SYNC, ptr->HeapID );
					Snd_BgmFadeOut( 0, WIPE_DEF_DIV*2 );

					(*seq)++;
				}
			}
			break;
		case 8:
			//フェードウェイト
			if( WIPE_SYS_EndCheck() ) {
				MSG_CNT_PrintEnd( ptr->MsgCnt );
				rc = TRUE;
			}
			break;
		}

		//メッセージ作成
		if( code != MSG_ID_NONE )
		{
			MSG_CNT_PrintMessage( ptr->MsgCnt, code );
			// メッセージシーケンスを進める
			ptr->MsgSeq++;
		}

	}

#ifdef PM_DEBUG
	// デバッグスキップ
	if( sys.trg == PAD_BUTTON_X )
	{
		// ワイプ状態を念のため解除
		WIPE_SYS_ExeEnd();
		MSG_CNT_PrintEnd( ptr->MsgCnt );
		return TRUE;
	}
#endif

	return rc;
}


//--------------------------------------------------------------------------------------
//タグ関連
//----------------------------------------------------------------------------
/**
 *	@brief	初期化
 *
 *	@param	*tagCntPtr	コントロールポインタ
 *	@param	inHeapID	ヒープID
 *	@param	bgl			BGL
 *	@param	pkthln_ptr　ポケスロンポインタ
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
static void InitTagControler(TAG_CNT *tagCntPtr, const int inHeapID,
		GF_BGL_INI *bgl, PKTHLN_PTR pkthln_ptr)
{
	tagCntPtr->RTagCntPtr = RTAG_Init(inHeapID, bgl, pkthln_ptr);
}

//----------------------------------------------------------------------------
/**
 *	@brief	セットアップ
 *
 *	@param	*tagCntPtr	コントロールポインタ
 *	@param	work		ポケスロンポインタ
 *	@param	inTotalRec	結果件数
 *	@param	inIconFlg	ポケモンアイコン有無
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
static void SetupTagControler(TAG_CNT *tagCntPtr, PKTHLN_PTR work, const u8 inTotalRec, const BOOL inIconFlg)
{
	int i;
	//総件数をセット
	tagCntPtr->TotalTagNum = inTotalRec;
	//タグコントローラセットアップ
	RTAG_Setup(tagCntPtr->RTagCntPtr, inIconFlg);

	//はじめの4件のデータを表示タグリストに登録
	for(i=0;i<DISP_TAG_NUM;i++){
		int wait = MV_START_WAIT * (i+1);
		RTAG_PTR tag_ptr = MakeTag( tagCntPtr, work, 256, (152+4) - (40*i) );

		// 一位はウェイト倍
		if( RTAG_GetRank(tag_ptr) == 0 )
		{
			wait += (MV_START_WAIT);
		}

		EntryTagToDispList(tagCntPtr, tag_ptr, wait);
	}
	//5件めがあるならば、スライドタグに設定
	if ( inTotalRec>DISP_TAG_NUM )
	{
		RTAG_PTR tag_ptr = MakeTag( tagCntPtr, work, 256, SLIDE_TAG_Y );
		EntryTagToSlide(tagCntPtr, tag_ptr, 0);
	}

	//コントローラのシーケンスをセット
	tagCntPtr->Seq = TAG_SEQ_SLIDE_IN_ALL;
}

//----------------------------------------------------------------------------
/**
 *	@brief	タグの移動
 *
 *	@param	data		タグデータ
 *	@param	inX			X移動
 *	@param	inY			Y移動
 *
 *	@return none
 */
//-----------------------------------------------------------------------------
static void MoveTag(TAG_DATA* data, const int inX, const int inY)
{
	if (!data->Valid){
		return;
	}
	//ウェイト消化
	if (data->MvWait == 0){
		//動作開始
		RTAG_MoveTag(data->TagPtr, inX, inY);
		if( data->bSndPlayed == FALSE )
		{
			//動作開始SE
			if( RTAG_GetRank(data->TagPtr) == 0 ){
				Snd_SePlay( SE_THLON_RANK_TOP );
			}else{
				Snd_SePlay( SE_THLON_RANK_234 );
			}
			data->bSndPlayed = TRUE;
		}
	}else{
		//待機
		data->MvWait--;
	}
}

//----------------------------------------------------------------------------
/**
 *	@brief	表示タグの移動
 *
 *	@param	*tagCntPtr	コントロールポインタ
 *	@param	inX			X移動
 *	@param	inY			Y移動
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
static void MoveDispTag(TAG_CNT *tagCntPtr, const int inX, const int inY)
{
	int i;
	TAG_DATA *data = tagCntPtr->DispTag;
	for(i=0;i<DISP_TAG_NUM;i++){
		MoveTag(&data[i], inX, inY);
	}
}

//----------------------------------------------------------------------------
/**
 *	@brief	座標到達チェック
 *
 *	@param	*data		タグデータポインタ
 *	@param	inFlg		チェックフラグ	CHECK_DIR参照
 *
 *	@return	BOOL	TRUE:到達	FALSE:未到達
 */
//-----------------------------------------------------------------------------
static BOOL CheckMoveArrive(TAG_DATA *data, const CHECK_DIR inFlg)
{
	int x,y;
	BOOL rc = FALSE;
	RTAG_GetTagPos( data->TagPtr, &x, &y );
	if (inFlg == CHECK_DIR_LEFT){
		if (x <= 0){
			RTAG_SetTagPos( data->TagPtr, 0, y );
			rc = TRUE;
		}
	}else if(inFlg == CHECK_DIR_DOWN){
		if (y >= 192){
			//画面外だから位置再設定しなくていいや
			rc = TRUE;
		}
	}

	return rc;
}

//----------------------------------------------------------------------------
/**
 *	@brief	ウェイトシーケンスシフト
 *
 *	@param	tagCntPtr	コントロールポインタ
 *	@param	inWait		待ち時間
 *
 *	@return none
 */
//-----------------------------------------------------------------------------
static void SetDispWaitSeq(TAG_CNT *tagCntPtr, const int inWait)
{
	tagCntPtr->Seq = TAG_SEQ_DISP_WAIT;
	tagCntPtr->Wait = inWait;
}

//----------------------------------------------------------------------------
/**
 *	@brief	タグ動作メイン
 *
 *	@param	tagCntPtr	コントロールポインタ
 *	@param	work		ポケスロンポインタ
 *
 *	@return	BOOL	TRUE:終了	FALSE:継続
 */
//-----------------------------------------------------------------------------
static BOOL TagSeqMain(TAG_CNT *tagCntPtr, PKTHLN_PTR work)
{
	TAG_DATA *data;
	u8 *seq = &tagCntPtr->Seq;

	switch(*seq){
	case TAG_SEQ_SLIDE_IN:		//新規スライドイン
		//新タグに横移動をリクエスト
		MoveTag(&tagCntPtr->SlideTag, -SLIDE_SPEED, 0);
		//規定位置まで到達したら、表示タグリストに追加
		if ( CheckMoveArrive(&tagCntPtr->SlideTag, CHECK_DIR_LEFT) ){
			//表示リストに追加
			EntryTagToDispList(tagCntPtr, tagCntPtr->SlideTag.TagPtr, 0);
			//スライドタグエントリを解除
			ClearTagEntry( &tagCntPtr->SlideTag );
			//次のタグがある場合、スライドインに備える
			if ( IsNoneDispTag(tagCntPtr) ){	//表示していないタグがある
				RTAG_PTR tag_ptr;
				//新規データ作成
				tag_ptr = MakeTag(tagCntPtr, work, NEW_TAG_X, SLIDE_TAG_Y);
				//スライドに登録
				EntryTagToSlide(tagCntPtr, tag_ptr, 0);
			}
			//シーケンスシフト:表示ウェイト
			SetDispWaitSeq(tagCntPtr, TAG_DISP_WAIT);
		}
		break;
	case TAG_SEQ_SLIDE_IN_ALL:	//初回4つタグのスライドイン
		{
			int i;
			//タグ全部に横移動をリクエスト
			MoveDispTag(tagCntPtr, -SLIDE_SPEED, 0);
			//全部のタグが規定位置に到達したら、シーケンスシフト:表示ウェイト
			data = tagCntPtr->DispTag;
			for(i=0;i<DISP_TAG_NUM;i++){
				if ( !CheckMoveArrive(&data[i], CHECK_DIR_LEFT) ){
					break;
				}
				// 初回一位が基底位置に到達したらMEを鳴らす
				else if (tagCntPtr->bFirstNo1 == FALSE )
				{
					if( RTAG_GetRank(data[i].TagPtr) == 0 )
					{
						Snd_MePlay( SEQ_ME_PT_RESULTG );
						tagCntPtr->bFirstNo1 = TRUE;
					}
				}
			}	//end for
			if (i==DISP_TAG_NUM){
				//全部到達
				SetDispWaitSeq(tagCntPtr, TAG_DISP_WAIT);
			}
		}
		break;
	case TAG_SEQ_MOVE_DOWN:		//表示中タグの下方向移動
		//タグ全部に下移動をリクエスト
		MoveDispTag(tagCntPtr, 0, DOWN_SPEED);
		//全タグ動作終了後一番したのタグが画面外に出たかチェック
		data = GetLastTag(tagCntPtr);
		if ( CheckMoveArrive(data, CHECK_DIR_DOWN) ){	//画面外に出た
			//タグ無効状態にする
			ClearTag(tagCntPtr, data);
			//シーケンスシフト:スライドイン
			(*seq) = TAG_SEQ_SLIDE_IN;
		}
		break;
	case TAG_SEQ_DISP_WAIT:
		//表示時間消化
		if (tagCntPtr->Wait-- <= 0){
			//まだタグがあるならば、タグスライドダウン
			if ( IsNoneDispTag( tagCntPtr ) ){
				(*seq) = TAG_SEQ_MOVE_DOWN;
			}else{//打ち止めなら終了
				return TRUE;
			}
		}
		break;
	}

	return FALSE;
}

//----------------------------------------------------------------------------
/**
 *	@brief	表示タグのエントリ
 *
 *	@param	*tagCntPtr		コントロールポインタ
 *	@param	tag_ptr			タグポインタ
 *	@param	inMvWait		動作開始ウェイト
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
static void EntryTagToDispList(TAG_CNT *tagCntPtr, RTAG_PTR tag_ptr, const int inMvWait)
{
	//登録タグ取得
	TAG_DATA *data;
	data = &tagCntPtr->DispTag[ tagCntPtr->EntryPoint ];

	GF_ASSERT(!(data->Valid));	//使用中ならアサート

	data->Valid = TRUE;
	data->TagPtr = tag_ptr;
	data->MvWait = inMvWait;

	//エントリポイントずらす
	tagCntPtr->EntryPoint = (tagCntPtr->EntryPoint+1)%DISP_TAG_NUM;
	//表示数をインクリメント
	tagCntPtr->NowTagNum++;
}

//----------------------------------------------------------------------------
/**
 *	@brief	スライドするタグのエントリ
 *
 *	@param	*tagCntPtr		コントロールポインタ
 *	@param	tag_ptr			タグポインタ
 *	@param	inMvWait		動作開始ウェイト

 *
 *	@return none
 */
//-----------------------------------------------------------------------------
static void EntryTagToSlide(TAG_CNT *tagCntPtr, RTAG_PTR tag_ptr, const int inMvWait)
{
	//登録タグ取得
	TAG_DATA *data;
	data = &tagCntPtr->SlideTag;

	GF_ASSERT(!data->Valid);

	data->Valid = TRUE;
	data->TagPtr = tag_ptr;
	data->MvWait = inMvWait;
}

//----------------------------------------------------------------------------
/**
 *	@brief	タグエントリのクリア
 *
 *	@param	outTagData		クリアするタグデータのポインタ
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
static void ClearTagEntry( TAG_DATA *outTagData )
{
	outTagData->Valid = FALSE;
	outTagData->TagPtr = NULL;
	outTagData->MvWait = 0;
}

//----------------------------------------------------------------------------
/**
 *	@brief	未表示のタグがあるか？
 *
 *	@param	*tagCntPtr	コントローラポインタ
 *
 *	@return	BOOL	TRUE:ある 	FALSE:ない
 */
//-----------------------------------------------------------------------------
static BOOL IsNoneDispTag( TAG_CNT *tagCntPtr )
{
	BOOL rc = FALSE;
	if ( tagCntPtr->TotalTagNum > tagCntPtr->NowTagNum ){
		rc = TRUE;
	}
	return rc;
}

//----------------------------------------------------------------------------
/**
 *	@brief	タグ作成
 *
 *	@param	*tagCntPtr		コントロールポインタ
 *	@param	work			ポケスロンポインタ
 *	@param	inX				作成X座標
 *	@param	inY 			作成Y座標
 *
 *	@return	tag_ptr			作成したタグのポインタ
 */
//-----------------------------------------------------------------------------
static RTAG_PTR MakeTag( TAG_CNT *tagCntPtr, PKTHLN_PTR work, const int inX, const int inY )
{
	RTAG_PTR	tag_ptr;
	RESULT_DATA *result;
	RSLT_PTR rslt;
	int last;
	rslt = PTFrame_GetResultPtr(work);
	//結果データを取得
	last = RSLT_GetDataNum(rslt)-1;
	result = RSLT_GetResultDataPtr(rslt, last - tagCntPtr->RsltReadPoint);
	//結果データ参照先を更新
	tagCntPtr->RsltReadPoint++;
	tag_ptr = RTAG_MakeTag( tagCntPtr->RTagCntPtr, inX, inY, result );

	return tag_ptr;
}

//----------------------------------------------------------------------------
/**
 *	@brief	タグデータのクリア
 *
 *	@param	*tagCntPtr		コントロールポインタ
 *	@param	*outTagData		タグデータポインタ
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
static void ClearTag(TAG_CNT *tagCntPtr, TAG_DATA *outTagData)
{
	RTAG_ClearTag( outTagData->TagPtr );
	ClearTagEntry( outTagData );
}

//----------------------------------------------------------------------------
/**
 *	@brief	画面一番したのタグデータポインタを返す
 *
 *	@param	*tagCntPtr	コントロールポインタ
 *
 *	@return	data		タグデータポインタ
 */
//-----------------------------------------------------------------------------
static TAG_DATA* GetLastTag(TAG_CNT *tagCntPtr)
{
	//エントリポイントの参照位置が一番下にきてるはず
	TAG_DATA *data;
	data = &tagCntPtr->DispTag[ tagCntPtr->EntryPoint ];
	return data;
}

//-----------------------------------------------------------------------------
/**
 *	@brief	リザルトシーン最初のメッセージを判定
 *
 *	@param	PKTHLN_PTR work
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
static u32 GetStartMsg( PKTHLN_PTR work )
{
	u8 crsID;
	int evtCnt;

	evtCnt = PTFrame_GetEventCounter( work );

	if( PTFrame_GetGameType( work ) == PKTHLN_GAME_ALONE )
	{
		return msg_pkthln_rs_se01_01 + evtCnt;
	}
	else
	{
		return msg_pkthln_rs_se01_04 + evtCnt;
	}
}

//-----------------------------------------------------------------------------
/**
 *	@brief
 *
 *	@param	PKTHLN_PTR work
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
static u32 GetEndMsg( PKTHLN_PTR work )
{
	u8 crsID;
	int evtCnt;
	COMM_EVENT_COMMON_DATA* data;
	RSLT_PARENT_DATA* parent;

	evtCnt = PTFrame_GetEventCounter( work );
	data = PTFrame_GetEvtComCmnData( work );
	parent = PKTHLN_CommPack_GetData( &data->ReciveShareData );

	HOSAKA_PRINT("evtCnt:%d rand:%d \n", evtCnt, parent->EndMesRand );
	GF_ASSERT( parent->EndMesRand < END_MES_RAND_MAX );

	if( PTFrame_GetGameType( work ) == PKTHLN_GAME_ALONE )
	{
		return msg_pkthln_rs_se03_01 + ( evtCnt * 5 ) + parent->EndMesRand;
	}
	else
	{
		return msg_pkthln_rs_se06_01 + ( evtCnt * 5 ) + parent->EndMesRand;
	}
}

//-----------------------------------------------------------------------------
/**
 *	@brief	CATSシステム生成
 *
 *	@param	PE_RESULT_PTR ptr
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
static void CATS_Create( PE_RESULT_PTR ptr )
{
	TCATS_RESOURCE_NUM_LIST crnl = { CHR_ID_MAX, PAL_ID_MAX, CEL_ID_MAX, ANM_ID_MAX, 0 };

	TCATS_OAM_INIT	coi = {
		0, 126,
		0, 32,
		1, 126,
		0, 32,
	};

	TCATS_CHAR_MANAGER_MAKE ccmm = {
		0,	// dummy
		1024*128,
		1024*16,
		GX_OBJVRAMMODE_CHAR_1D_64K,
		GX_OBJVRAMMODE_CHAR_1D_64K,
	};
	ccmm.num = OBJ_ID_MAX;

	ptr->csp = CATS_AllocMemory( ptr->HeapID );
	ptr->crp = CATS_ResourceCreate( ptr->csp );

	CATS_SystemInit( ptr->csp, &coi, &ccmm, 32 );
	CATS_ClactSetInit( ptr->csp, ptr->crp, CAP_ID_MAX );
	CATS_ResourceManagerInit( ptr->csp, ptr->crp, &crnl );
}

//-----------------------------------------------------------------------------
/**
 *	@brief	CATSシステム開放
 *
 *	@param	PE_RESULT_PTR ptr
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
static void CATS_Delete( PE_RESULT_PTR ptr )
{
	u8 i;
	for( i=0; i<CAP_ID_MAX; i++ )
	{
		if( ptr->cap[i] != NULL )
		{
			CATS_ActorPointerDelete_S( ptr->cap[i] );
			ptr->cap[i] = NULL;
		}
	}

	CATS_ResourceDestructor_S( ptr->csp, ptr->crp );
	CATS_FreeMemory( ptr->csp );
}


//-----------------------------------------------------------------------------
/**
 *	@brief	トレーナー用ダーミーリソースを展開
 *
 *	@param	PE_RESULT_PTR ptr
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
static void CATS_LoadRes( PE_RESULT_PTR ptr )
{
	u8 i;
	u32 cgr_idx = NARC_pkthev_oped_obj_dmy_lz_ncgr;
	u32 cell_idx = NARC_pkthev_oped_obj_dmy_lz_ncer;
	u32 anm_idx = NARC_pkthev_oped_obj_dmy_lz_nanr;
	u32 pal_idx = NARC_pkthev_oped_obj_dmy_nclr;
	CATS_SYS_PTR csp = ptr->csp;
	CATS_RES_PTR crp = ptr->crp;

	// LCD SUB
	CATS_LoadResourceCharArc( csp, crp, ARC_PKTHEV_OPED, cgr_idx, TRUE, NNS_G2D_VRAM_TYPE_2DSUB, CHR_ID_S_MMO );
	CATS_LoadResourcePlttArc( csp, crp, ARC_PKTHEV_OPED, pal_idx, 0, 1, NNS_G2D_VRAM_TYPE_2DSUB, PAL_ID_S_MMO );

	CATS_LoadResourceCellArc(		csp, crp, ARC_PKTHEV_OPED, cell_idx, TRUE, CEL_ID_MMO );
	CATS_LoadResourceCellAnmArc(	csp, crp, ARC_PKTHEV_OPED, anm_idx, TRUE, ANM_ID_MMO );
}

//-----------------------------------------------------------------------------
/**
 *	@brief	CATSにマップモデル表示用アクターを追加（この時点ではダミー絵）
 *
 *	@param	PE_RESULT_PTR ptr
 *
 *	@retval
 */
//-----------------------------------------------------------------------------
static void CATS_AddMapModel( PE_RESULT_PTR ptr )
{
	TCATS_OBJECT_ADD_PARAM_S prm = {0};
	int i;

	// LCD Sub
	prm.id[0] = CHR_ID_S_MMO;
	prm.id[1] = PAL_ID_S_MMO;
	prm.id[2] = CEL_ID_MMO;
	prm.id[3] = ANM_ID_MMO;
	prm.d_area = NNS_G2D_VRAM_TYPE_2DSUB;
	prm.bg_pri = 1;
	prm.x = 28*8;
	prm.y = 14*8;

	ptr->cap[ CAP_ID_S_TALKER ] = CATS_ObjectAdd_S( ptr->csp, ptr->crp, &prm );
}

//-----------------------------------------------------------------------------
/**
 *	@brief	OPENING 通信処理
 *
 *	@param	PKTHLN_PTR work
 *
 *	@retval TRUE:同期中
 */
//-----------------------------------------------------------------------------
static BOOL RSLT_CommMain( PKTHLN_PTR work )
{
	int i;
	PE_RESULT_PTR ptr = PTFrame_GetEventWorkPtr(work);
	COMM_EVENT_COMMON_DATA* data = PTFrame_GetEvtComCmnData(work);
	RSLT_PARENT_DATA* parent = PKTHLN_CommPack_GetData( &data->SendShareData );
	RSLT_PARENT_DATA* parent_rec = PKTHLN_CommPack_GetData( &data->ReciveShareData );

	u8 MyNetID = PTFrameGetCurrentID(work);
	u8 LocalMsgSeq = ptr->MsgSeq;

	BOOL bDelay = FALSE;

	// 親処理
	if( MyNetID == COMM_PARENT_ID )
	{
		BOOL bEnd = TRUE;

		// 送信メッセージシーケンス セット
		parent->MsgSeq = LocalMsgSeq;

		// 親の子機データは直接レシーバにセット
		{
			RSLT_COMM_CHILD_PTR child;
			RSLT_COMM_CHILD_PTR child_rec;

			child_rec = PKTHLN_CommPack_GetData(&data->ReciveData[0]);
			child = PKTHLN_CommPack_GetData(&data->SendData);
			(*child_rec) = (*child);
		}

		// レシーバー集計
		// (AIはメッセージを待たないので飛ばす)
		for( i=0; i<PTFrame_GetPlayerNum(work); i++ )
		{
			RSLT_COMM_CHILD_PTR child_rec;

			child_rec = PKTHLN_CommPack_GetData(&data->ReciveData[i]);

			//------------------------------------------------------
			// 子のメッセージシーケンスが親とずれているか判定
			//------------------------------------------------------
			// ・メッセージシーケンスが遅れている
			// ・もしくは一人でもメッセージ表示中の奴がいる
			//------------------------------------------------------
			if( ( child_rec->MsgSeq < LocalMsgSeq ) || child_rec->bPrinting == TRUE )
			{
//				OS_TPrintf( "ParentMsgSeq:%d delay[%d] MsgSeq:%d \n", LocalMsgSeq, i, child_rec->MsgSeq );
				bDelay = TRUE;
			}

			//--------------------------------------------
			// 終了判定
			//--------------------------------------------
			if( child_rec->EndFlag == FALSE )
			{
				bEnd = FALSE;
			}
		}

		// 子機全員のEndFlagが立っていれば親機のEndFlagを立てる
		if( bEnd )
		{
			parent->EndFlag = TRUE;
		}

		//--------------------------------------------
		// メッセージウェイト判定保持
		//--------------------------------------------
		// ・一人でもずれていれば全員メッセージウェイトして良い
		// ・メッセージ表示以外のシーケンスが止まってしまうと困る
		//--------------------------------------------
		parent->bMsgWait = bDelay;

	} // end of parent proc

	// 子機 データ送信
	{
		RSLT_COMM_CHILD_PTR child = PKTHLN_CommPack_GetData(&data->SendData);

		child->MsgSeq = LocalMsgSeq;
		child->bPrinting = MSG_CNT_IsPrinting( ptr->MsgCnt );
		child->EndFlag = ptr->EndFlag;
	} // end of child proc

	// 子機判定
	//・シェアデータのメッセージウェイトフラグが立っているとメッセージウェイト
	//・もし親の方がシーケンスが進んでいた場合、メッセージウェイトしない。
	return ( parent_rec->bMsgWait && LocalMsgSeq >= parent_rec->MsgSeq );

}
